package cn.sdxx.qddata.config;


import cn.sdxx.qddata.security.JwtFilter;
import cn.sdxx.qddata.security.MyCredentialsMatcher;
import cn.sdxx.qddata.security.UserRealm;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.mgt.SessionsSecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.IRedisManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.util.Pool;
import redis.clients.jedis.JedisPool;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro启用注解拦截控制器
 */
@Configuration
public class ShiroConfig {
    @Autowired
    RedisSessionDAO redisSessionDAO;

    @Autowired
    RedisCacheManager redisCacheManager;

//    @Autowired
//    JwtFilter jwtFilter;

    @Autowired
    private MyCredentialsMatcher myCredentialsMatcher;



    @Bean
    public SessionManager sessionManager() {
        // 使用自定义的sessionManager，实现将token缓存起来
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionDAO(redisSessionDAO);
        //禁用cookie
        sessionManager.setSessionIdCookieEnabled(false);
        // 禁用会话id重写
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    @Bean
    public SessionsSecurityManager securityManager(UserRealm accountRealm,
                                                   SessionManager sessionManager) {
//        accountRealm.setCredentialsMatcher(myCredentialsMatcher);
        //启用realm缓存
        accountRealm.setCachingEnabled(true);
        //启用身份验证缓存，即缓存AuthenticationInfo信息，默认false
        accountRealm.setAuthenticationCachingEnabled(true);
        //启用授权缓存，即缓存AuthorizationInfo信息，默认false
        accountRealm.setAuthorizationCachingEnabled(true);
        //为了方便操作，我们给缓存起个名字
        accountRealm.setAuthenticationCacheName("authentication");  //认证cache
//        accountRealm.setAuthorizationCacheName("authorization");    //授权cache
        //注入缓存实现，需要配合EhCache
        //accountRealm.setCacheManager(new EhCacheManager());


        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(accountRealm);

        //inject sessionManager
        securityManager.setSessionManager(sessionManager);

        // inject redisCacheManager
        // shiro-redis要求放在session里面的实体类必须有个id标识
//        redisCacheManager.setPrincipalIdFieldName("id");
        redisCacheManager.setPrincipalIdFieldName("username");
        securityManager.setCacheManager(redisCacheManager);

        /*
         * 关闭shiro自带的session，详情见文档
         */
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        //设置SessionStorageEnabled为false（默认是true）
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        return securityManager;
    }

    //定义拦截路径
    // 在spring容器中使用ShiroFilterChainDefinition来控制所有url的鉴权和授权。
    // 优点是配置粒度大，对多个Controller做鉴权授权的控制。
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();

        Map<String, String> filterMap = new LinkedHashMap<>();
        filterMap.put("/user/login", "anon");    //不拦截登录接口
        filterMap.put("/user/reg", "anon");    //不拦截注册接口
        filterMap.put("/favicon.ico", "anon");
        filterMap.put("/joke", "anon");
        filterMap.put("/joke/**", "anon");
        filterMap.put("/doc.html", "anon");    //不拦截knife4j接口
        filterMap.put("/doc.html/**", "anon");    //不拦截knife4j接口
        filterMap.put("/doc.html#/**", "anon");    //不拦截knife4j接口
        filterMap.put("/swagger-ui.html", "anon");    //不拦截knife4j接口
        filterMap.put("/swagger-resources", "anon");    //不拦截knife4j接口
        filterMap.put("/swagger-resources/**", "anon");    //不拦截knife4j接口
        filterMap.put("/webjars/**", "anon");    //不拦截knife4j接口
        filterMap.put("/v2/api-docs-ext", "anon");
        filterMap.put("/v2/api-docs", "anon");    //不拦截knife4j接口
        filterMap.put("/**", "jwt");    // 主要通过注解方式校验权限
        chainDefinition.addPathDefinitions(filterMap);
        return chainDefinition;
    }


    @Bean("shiroFilterFactoryBean")     //通过方法名注入
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager,
                                                         ShiroFilterChainDefinition shiroFilterChainDefinition) {
        //参数中SecurityManager默认会使用JDK的，重新导入包
        // import org.apache.shiro.mgt.SecurityManager;
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);

        //设置过滤器
        Map<String, Filter> filters = new HashMap<>();

        // 这里不能注入的jwtFilter，改用new，不然所有路径都被jwtFilter拦截
        // filters.put("jwt", jwtFilter);
        filters.put("jwt", new JwtFilter());
        shiroFilter.setFilters(filters);
        // 设置哪个路径走哪个过滤器
        Map<String, String> filterMap = shiroFilterChainDefinition.getFilterChainMap();
        shiroFilter.setFilterChainDefinitionMap(filterMap);


        return shiroFilter;
    }

    /**
     * Shiro生命周期处理器
     */
    @Bean(name = "lifecycleBeanPostProcessor")
    public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }


    // 开启注解代理（默认好像已经开启，可以不要）
    // 开启Shiro-aop注解支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    //自动创建代理（开启注解的依赖）
    @Bean
    public static DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setUsePrefix(true);
        return creator;
    }


}
